package com.baitiaojun.moments.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baitiaojun.api.domain.moments.UserMoments;
import com.baitiaojun.api.domain.moments.UserMomentsStatus;
import com.baitiaojun.api.domain.moments.UserVideoMoments;
import com.baitiaojun.api.domain.user.UserInfo;
import com.baitiaojun.api.domain.video.Video;
import com.baitiaojun.api.exception.ConditionException;
import com.baitiaojun.api.util.AESUtil;
import com.baitiaojun.api.util.ConstantUtil;
import com.baitiaojun.api.util.SnowFlakeUtil;
import com.baitiaojun.api.vo.JsonRes;
import com.baitiaojun.moments.config.AsyncConfig;
import com.baitiaojun.moments.feign.UserFeign;
import com.baitiaojun.moments.feign.VideoFeign;
import com.baitiaojun.moments.handler.RabbitMqHandler;
import com.baitiaojun.moments.mapper.UserVideoMomentsMapper;
import com.baitiaojun.moments.service.DuplicateService;
import com.baitiaojun.moments.service.MomentsService;
import com.baitiaojun.moments.service.MomentsStatusService;
import com.baitiaojun.moments.service.VideoMomentsService;
import com.baitiaojun.moments.support.RedisSupport;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;

import javax.annotation.Resource;
import java.util.Date;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @类名 UserVideoMomentsServiceImpl
 * @作者 白条君
 * @创建日期 2023/1/16 13:09
 * @版本 1.0
 */
@Service
public class VideoMomentsServiceImpl implements VideoMomentsService {

    @Autowired
    private VideoFeign videoFeign;

    @Autowired
    private MomentsService momentsService;

    @Autowired
    private DuplicateService duplicateService;

    @Autowired
    private RabbitMqHandler rabbitMqhandler;

    @Resource
    private UserVideoMomentsMapper userVideoMomentsMapper;

    @Autowired
    private UserFeign userFeign;

    @Autowired
    private MomentsStatusService momentsStatusService;

    @Autowired
    private TransactionDefinition definition;

    @Autowired
    private PlatformTransactionManager transactionManager;

    @Autowired
    private AsyncConfig asyncConfig;

    @Autowired
    private RedisSupport redisSupport;

    @Override
    public void publishVideoMoments(Long videoId, Long userId) throws ConditionException {
        TransactionStatus status = transactionManager.getTransaction(definition);
        //查询momentsstatus
        UserMomentsStatus momentsStatus = momentsStatusService.getMomentsStatusByContentId(videoId);
        if (ObjectUtils.isEmpty(momentsStatus)) {
            throw new ConditionException("没有此动态状态信息");
        }
        Long momentsStatusId = momentsStatus.getId();
        momentsStatus.setId(momentsStatusId);
        momentsStatus.setUpdatetime(new Date());
        try {
            //采用延时双删策略，先对缓存进行删除
            redisSupport.asyncDelete(userId);
            //添加视频详情信息
            UserVideoMoments userVideoMoments = new UserVideoMoments();
            Long contentId = SnowFlakeUtil.getNextId();
            userVideoMoments.setId(contentId);
            userVideoMoments.setVideoId(videoId);
            userVideoMoments.setCreateTime(new Date());
            userVideoMoments.setDescription(ConstantUtil.VIDEO_MOMENTS_DESCRIPTION);
            this.saveUserVideoMoments(userVideoMoments);
            //存储关联表usermoments
            UserMoments userMoments = new UserMoments();
            Long momentsId = SnowFlakeUtil.getNextId();
            userMoments.setId(momentsId);
            userMoments.setContentid(contentId);
            userMoments.setUserid(userId);
            userMoments.setType(ConstantUtil.VIDEO_TYPE);
            userMoments.setCreatetime(new Date());
            momentsService.addUserMoments(userMoments);
            //冗余存储到mysql
            Long duplicateId = duplicateService.insertDuplicate(userMoments);
            if (ObjectUtils.isEmpty(duplicateId)) {
                throw new ConditionException("无法获取冗余存储id");
            }
            //提交事务
            transactionManager.commit(status);
            //提交成功后修改为处理成功
            momentsStatus.setStatus(ConstantUtil.SUCCESS_STATUS);
            momentsStatusService.editMomentsStatus(momentsStatus);
            //发布动态
            rabbitMqhandler.publishMoments(userMoments, duplicateId);
        } catch (Exception e) {
            transactionManager.rollback(status);
            //提交失败修改动态状态
            if (ObjectUtils.isNotEmpty(momentsStatus)) {
                momentsStatus.setTrycount(momentsStatus.getTrycount());
                momentsStatus.setStatus(ConstantUtil.FAIL_STATUS);
                momentsStatusService.editMomentsStatus(momentsStatus);
            }
        }
    }

    @Override
    public Long getVideoMomentsIdByVideoId(Long videoId) {
        return userVideoMomentsMapper.selectContentIdByVideoId(videoId);
    }

    @Override
    public void saveUserVideoMoments(UserVideoMoments userVideoMoments) throws ConditionException {
        int res = userVideoMomentsMapper.insertSelective(userVideoMoments);
        if (res == 0) {
            throw new ConditionException("添加视频动态失败");
        }
    }

    @Override
    public UserVideoMoments getUserVideoMoments(Long contentId, Long userId) throws Exception {
        if (ObjectUtils.isEmpty(contentId) || ObjectUtils.isEmpty(userId)) {
            throw new ConditionException("参数异常");
        }
        UserVideoMoments userVideoMoments = userVideoMomentsMapper.selectByPrimaryKey(contentId);
        //获取倒计时计数器
        CountDownLatch latch = new CountDownLatch(4);
        //获取线程池执行器
        Executor executor = asyncConfig.getAsyncExecutor();
        if (ObjectUtils.isEmpty(executor)) {
            throw new ConditionException("无法获取线程池执行器");
        }
        //获取aes工具类
        AESUtil aesUtil = AESUtil.lazyGetAesUtil();
        //添加动态发布者
        executor.execute(() -> {
            try {
                UserInfo userInfo = userFeign.getUserInfo(userId);
                if (ObjectUtils.isNotEmpty(userInfo)) {
                    userInfo.setAvatar(aesUtil.encrypt(userInfo.getAvatar()));
                    userInfo.setUserid(null);
                    userInfo.setFollowing(null);
                    userInfo.setFollowed(null);
                    userInfo.setBirth(null);
                    userInfo.setCoinCount(null);
                    userInfo.setFansCount(null);
                    userInfo.setGender(null);
                    userInfo.setCreatetime(null);
                    userInfo.setUpdatetime(null);
                    userVideoMoments.setUserInfo(userInfo);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            latch.countDown();
        });
        //添加动态基本信息
        JsonRes jsonRes = videoFeign.getVideoDetails(userVideoMoments.getVideoId());
        if (jsonRes.get("status").equals(500)) {
            throw new ConditionException("获取视频详情失败");
        }
        Map<String, Object> videoDetailsMap = JSONObject.parseObject(JSONObject.toJSONString(jsonRes.get("data")));
        if (ObjectUtils.isEmpty(videoDetailsMap)) {
            throw new ConditionException("获取视频详情失败");
        }
        Video video = JSONObject.parseObject(JSONObject.toJSONString(videoDetailsMap.get("video")), Video.class);
        Long videoId = video.getId();
        //获取videocommentcount
        AtomicInteger videoCommentCount = new AtomicInteger(0);
        executor.execute(() -> {
            videoCommentCount.set(videoFeign.getVideoCommentCount(videoId));
            latch.countDown();
        });
        //获取videolikecount
        AtomicInteger videoLikeCount = new AtomicInteger(0);
        executor.execute(() -> {
            try {
                JsonRes res = videoFeign.getVideoLike(videoId);
                if (res.get("status").equals(1)) {
                    Map<String, Object> map = (Map<String, Object>) res.get("data");
                    videoLikeCount.set((Integer) map.get("count"));
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            latch.countDown();
        });
        //获取videoviewcount
        AtomicInteger videoViewCount = new AtomicInteger(0);
        executor.execute(() -> {
            JsonRes resViewCount = videoFeign.getVideoViewCount(videoId);
            if (resViewCount.get("status").equals(1)) {
                videoViewCount.set((Integer) resViewCount.get("data"));
            }
            latch.countDown();
        });
        latch.await();
        //添加视频动态信息
        userVideoMoments.setVideo(Video.builder()
                .title(video.getTitle())
                .thumbnail(video.getThumbnail())
                .viewCount(videoViewCount.get())
                .commentCount(videoCommentCount.get())
                .lickCount(videoLikeCount.get())
                .duration(video.getDuration()).build()
        );
        return userVideoMoments;
    }
}
